#ifndef __tenacitas_async__executer__h__
#define __tenacitas_async__executer__h__

// =============================================================================
/**
@file 
File description
*/


// =============================================================================
//                                 C++ Headers

#include <tuple>

// =============================================================================
//                                 3rds Headers


// =============================================================================
//                                 Our Headers


// =============================================================================
//                                 Namespaces
using namespace std;


// =============================================================================
//                                 Macro Contants

/**
*/


// =============================================================================
//                                 Macro Commands

/**
*/


/**
namespace of the organization
*/
namespace tenacitas {
    /**
    namespace for the project
    */
    namespace async {

        // =========================== Typedefs ===========================
        /** */


        // ============================ Pre-Declarations ==================


        // ============================ Attributes ========================
        /** */


        // ============================ Functions =========================
        /** */


        // ============================ Classes ===========================

        /** Base template class */
        template<typename t_handlers, typename t_event, uint8_t num_params>
        struct executer;

        /** Passes to a type of pool of handlers an event with no parameters */ 
        template<typename t_handlers>
        struct executer<t_handlers, std::tuple<>, 0> {
            void operator( )( t_handlers * p_handlers, std::tuple<> & ) {                
                p_handlers->handle( );
            }
        };

        /** Passes to a type of pool of handlers an event with one parameter */
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 1> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;

                std::tie( l_0 ) = p_event;

                p_handlers->handle( l_0 );
            }
        };

        /** Passes to a type of pool of handlers an event with two parameters */ 
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 2> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;

                std::tie( l_0, l_1 ) = p_event;    

                p_handlers->handle( l_0, l_1 );
            }
        };

        /** Passes to a type of pool of handlers an event with three parameters */ 
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 3> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;

                std::tie( l_0, l_1, l_2 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2 );
            }
        };

        /** Passes to a type of pool of handlers an event with four parameters */ 
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 4> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;

                std::tie( l_0, l_1, l_2, l_3 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3 );
            }
        };

        /** Passes to a type of pool of handlers an event with five parameters */ 
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 5> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;

                std::tie( l_0, l_1, l_2, l_3, l_4 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4 );
            }
        };

        
        /** Passes to a type of pool of handlers an event with six parameters */
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 6> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5 );
            }
        };

        /** Passes to a type of pool of handlers an event with seven parameters */
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 7> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_6 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6 );
            }
        };

        /** Passes to a type of pool of handlers an event with eight parameters */
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 8> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6, l_7 );
            }
        };

        /** Passes to a type of pool of handlers an event with nine parameters */
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 9> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7, l_8 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8 );
            }
        };

        /** Passes to a type of pool of handlers an event with ten parameters */
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 10> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;
                typename std::tuple_element<9, t_event>::type l_9;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9 );
            }
        };
        /*
        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 11> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;
                typename std::tuple_element<9, t_event>::type l_9;
                typename std::tuple_element<10, t_event>::type l_10;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7, l_8, l_9, l_10 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6 l_7, l_8, l_9, l_10 );
            }
        };

        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 12> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;
                typename std::tuple_element<9, t_event>::type l_9;
                typename std::tuple_element<10, t_event>::type l_10;
                typename std::tuple_element<11, t_event>::type l_11;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7, l_8, l_9, l_10, l_11 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6 l_7, l_8, l_9, l_10, l_11 );
            }
        };

        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 13> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;
                typename std::tuple_element<9, t_event>::type l_9;
                typename std::tuple_element<10, t_event>::type l_10;
                typename std::tuple_element<11, t_event>::type l_11;
                typename std::tuple_element<12, t_event>::type l_12;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7, l_8, l_9, l_10, l_11, l_12 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6 l_7, l_8, l_9, l_10, l_11, l_12 );
            }
        };

        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 14> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;
                typename std::tuple_element<9, t_event>::type l_9;
                typename std::tuple_element<10, t_event>::type l_10;
                typename std::tuple_element<11, t_event>::type l_11;
                typename std::tuple_element<12, t_event>::type l_12;
                typename std::tuple_element<13, t_event>::type l_13;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7, l_8, l_9, l_10, l_11, l_12, l_13 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6 l_7, l_8, l_9, l_10, l_11, l_12, l_13 );
            }
        };

        template<typename t_handlers, typename t_event>
        struct executer<t_handlers, t_event, 15> {
            void operator( )( t_handlers * p_handlers, t_event & p_event ) {
                typename std::tuple_element<0, t_event>::type l_0;
                typename std::tuple_element<1, t_event>::type l_1;
                typename std::tuple_element<2, t_event>::type l_2;
                typename std::tuple_element<3, t_event>::type l_3;
                typename std::tuple_element<4, t_event>::type l_4;
                typename std::tuple_element<5, t_event>::type l_5;
                typename std::tuple_element<6, t_event>::type l_6;
                typename std::tuple_element<7, t_event>::type l_7;
                typename std::tuple_element<8, t_event>::type l_8;
                typename std::tuple_element<9, t_event>::type l_9;
                typename std::tuple_element<10, t_event>::type l_10;
                typename std::tuple_element<11, t_event>::type l_11;
                typename std::tuple_element<12, t_event>::type l_12;
                typename std::tuple_element<13, t_event>::type l_13;
                typename std::tuple_element<14, t_event>::type l_14;

                std::tie( l_0, l_1, l_2, l_3, l_4, l_5, l_7, l_8, l_9, l_10, l_11, l_12, l_13, l_14 ) = p_event;

                p_handlers->handle( l_0, l_1, l_2, l_3, l_4, l_5, l_6 l_7, l_8, l_9, l_10, l_11, l_12, l_13, l_14 );
            }
        };*/

    }
}

// =============================================================================
//                     I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::async;


#endif
